#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>

#include "server.h"
#include "cJSON.h"
#include "log.h"
#include "common.h"
#include "database.h"
#include "user.h"

// 全局变量
ThreadPool *g_threadPool = NULL;
int g_epollfd = -1;
ClientInfo *g_clients[MAX_CLIENT_COUNT];
int g_clientCount = 0;

// 处理硅片数据
void processSiliconWaferData(ClientInfo *client, cJSON *root) {
    cJSON *batchData = cJSON_GetObjectItem(root, "batchSiliconWaferData");
    if (batchData && (batchData->type == cJSON_Array)) {
        int arraySize = cJSON_GetArraySize(batchData);
        logInfo("Received %d silicon wafer data records from client %s:%d", 
                arraySize, inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port));
        
        // 处理每条硅片数据
        for (int i = 0; i < arraySize; i++) {
            cJSON *item = cJSON_GetArrayItem(batchData, i);
            if (item) {
                char *waferId = cJSON_GetObjectItem(item, "waferId")->valuestring;
                char *defectType = cJSON_GetObjectItem(item, "defectType")->valuestring;
                double efficiency = cJSON_GetObjectItem(item, "efficiency")->valuedouble;
                
                logDebug("Wafer ID: %s, Defect Type: %s, Efficiency: %.2f", 
                        waferId, defectType, efficiency);
                
                // 这里可以添加数据存储逻辑
            }
        }
    }
}

// 处理生产数据
void processProductionData(ClientInfo *client, cJSON *root) {
    // 检查是否是productionData（详细生产数据）
    cJSON *prodData = cJSON_GetObjectItem(root, "productionData");
    if (prodData && (prodData->type == cJSON_Object)) {
        // 从JSON中提取生产数据字段
        char *waferid = cJSON_GetObjectItem(prodData, "waferid")->valuestring;
        char *equipmentid = cJSON_GetObjectItem(prodData, "equipmentid")->valuestring;
        char *defecttyme = cJSON_GetObjectItem(prodData, "defecttyme")->valuestring;
        char *productionline = cJSON_GetObjectItem(prodData, "productionline")->valuestring;
        char *reworkflag = cJSON_GetObjectItem(prodData, "reworkflag")->valuestring;
        char *idaddress = cJSON_GetObjectItem(prodData, "idaddress")->valuestring;
        
        logInfo("Received production data from client %s:%d - Wafer ID: %s, Production Line: %s", 
                inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port),
                waferid, productionline);
        
        // 连接数据库并存储数据
        MYSQL *conn = dbConnect();
        if (conn) {
            if (dbInsertProductionData(conn, waferid, equipmentid, defecttyme, 
                                     productionline, reworkflag, idaddress) < 0) {
                // 发送错误响应
                cJSON *response = cJSON_CreateObject();
                cJSON_AddStringToObject(response, "error", "Failed to save production data");
                char *responseStr = cJSON_PrintUnformatted(response);
                sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
                free(responseStr);
                cJSON_Delete(response);
            } else {
                // 发送成功响应
                cJSON *response = cJSON_CreateObject();
                cJSON_AddStringToObject(response, "status", "success");
                char *responseStr = cJSON_PrintUnformatted(response);
                sendPacket(client->sockfd, DATA_TYPE_ACK, responseStr);
                free(responseStr);
                cJSON_Delete(response);
                
                // 检查是否需要执行小时统计（每小时执行一次）
                time_t now = time(NULL);
                struct tm *tm = localtime(&now);
                if (tm->tm_min == 0 && tm->tm_sec < 10) {  // 在整点后10秒内执行
                    char timeRange[14];
                    strftime(timeRange, sizeof(timeRange), "%Y-%m-%d %H:00", tm);
                    dbSummarizeHourlyData(conn, timeRange);
                }
            }
            dbDisconnect(conn);
        } else {
            // 数据库连接失败，发送错误响应
            cJSON *response = cJSON_CreateObject();
            cJSON_AddStringToObject(response, "error", "Database connection failed");
            char *responseStr = cJSON_PrintUnformatted(response);
            sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
            free(responseStr);
            cJSON_Delete(response);
        }
    } 
    // 检查是否是productionSummary（生产统计数据）
    else {
        cJSON *summaryData = cJSON_GetObjectItem(root, "productionSummary");
        if (summaryData && (summaryData->type == cJSON_Object)) {
            // 从JSON中提取统计数据字段
            char *shift = cJSON_GetObjectItem(summaryData, "shift")->valuestring;
            char *time = cJSON_GetObjectItem(summaryData, "time")->valuestring;
            char *lineno = cJSON_GetObjectItem(summaryData, "lineno")->valuestring;
            int output = cJSON_GetObjectItem(summaryData, "output")->valueint;
            double qualifiedrata = cJSON_GetObjectItem(summaryData, "qualifiedrata")->valuedouble;
            double Agraderata = cJSON_GetObjectItem(summaryData, "Agraderata")->valuedouble;
            double reworkrata = cJSON_GetObjectItem(summaryData, "reworkrata")->valuedouble;
            
            logInfo("Received production summary from client %s:%d - Line: %s, Time: %s, Output: %d", 
                    inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port),
                    lineno, time, output);
            
            // 连接数据库并存储统计数据
            MYSQL *conn = dbConnect();
            if (conn) {
                if (dbInsertProductionSummary(conn, shift, time, lineno, output, 
                                           qualifiedrata, Agraderata, reworkrata) < 0) {
                    // 发送错误响应
                    cJSON *response = cJSON_CreateObject();
                    cJSON_AddStringToObject(response, "error", "Failed to save production summary");
                    char *responseStr = cJSON_PrintUnformatted(response);
                    sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
                    free(responseStr);
                    cJSON_Delete(response);
                } else {
                    // 发送成功响应
                    cJSON *response = cJSON_CreateObject();
                    cJSON_AddStringToObject(response, "status", "success");
                    char *responseStr = cJSON_PrintUnformatted(response);
                    sendPacket(client->sockfd, DATA_TYPE_ACK, responseStr);
                    free(responseStr);
                    cJSON_Delete(response);
                }
                dbDisconnect(conn);
            } else {
                // 数据库连接失败，发送错误响应
                cJSON *response = cJSON_CreateObject();
                cJSON_AddStringToObject(response, "error", "Database connection failed");
                char *responseStr = cJSON_PrintUnformatted(response);
                sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
                free(responseStr);
                cJSON_Delete(response);
            }
        }
    }
}

// 处理用户登录请求
void handleUserLogin(ClientInfo *client, cJSON *root) {
    char *username = cJSON_GetObjectItem(root, "username")->valuestring;
    char *password = cJSON_GetObjectItem(root, "password")->valuestring;
    
    logInfo("Login request from %s:%d - username: %s", 
            inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port), username);
    
    // 连接数据库
    MYSQL *conn = dbConnect();
    if (!conn) {
        // 发送错误响应
        cJSON *response = cJSON_CreateObject();
        cJSON_AddStringToObject(response, "error", "Database connection failed");
        char *responseStr = cJSON_PrintUnformatted(response);
        sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
        free(responseStr);
        cJSON_Delete(response);
        return;
    }
    
    // 查询用户信息
    UserInfo user;
    if (dbGetUser(conn, username, &user) == 0 && strcmp(user.password, password) == 0) {
        // 登录成功
        cJSON *response = cJSON_CreateObject();
        cJSON_AddStringToObject(response, "role", user.role);
        char *responseStr = cJSON_PrintUnformatted(response);
        sendPacket(client->sockfd, DATA_TYPE_ACK, responseStr);
        free(responseStr);
        cJSON_Delete(response);
        
        logInfo("User login successful: %s", username);
        
        // 记录日志到数据库
        time_t now = time(NULL);
        char timeStr[20];
        strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", localtime(&now));
        dbInsertLog(conn, (int)now, timeStr, "", "User login successful");
    } else {
        // 登录失败
        cJSON *response = cJSON_CreateObject();
        cJSON_AddStringToObject(response, "error", "Invalid username or password");
        char *responseStr = cJSON_PrintUnformatted(response);
        sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
        free(responseStr);
        cJSON_Delete(response);
        
        logWarning("User login failed: %s", username);
        
        // 记录日志到数据库
        time_t now = time(NULL);
        char timeStr[20];
        strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", localtime(&now));
        dbInsertLog(conn, (int)now, timeStr, "Login failed", "Invalid username or password");
    }
    
    dbDisconnect(conn);
}

// 处理用户注册请求
void handleUserRegister(ClientInfo *client, cJSON *root) {
    char *username = cJSON_GetObjectItem(root, "username")->valuestring;
    char *password = cJSON_GetObjectItem(root, "password")->valuestring;
    char *role = cJSON_GetObjectItem(root, "role")->valuestring;
    
    logInfo("Register request from %s:%d - username: %s, role: %s", 
            inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port), username, role);
    
    // 连接数据库
    MYSQL *conn = dbConnect();
    if (!conn) {
        // 发送错误响应
        cJSON *response = cJSON_CreateObject();
        cJSON_AddStringToObject(response, "error", "Database connection failed");
        char *responseStr = cJSON_PrintUnformatted(response);
        sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
        free(responseStr);
        cJSON_Delete(response);
        return;
    }
    
    // 检查用户是否已存在
    if (dbCheckUserExists(conn, username)) {
        // 用户已存在
        cJSON *response = cJSON_CreateObject();
        cJSON_AddStringToObject(response, "error", "User already exists");
        char *responseStr = cJSON_PrintUnformatted(response);
        sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
        free(responseStr);
        cJSON_Delete(response);
        
        logWarning("User registration failed: %s already exists", username);
    } else {
        // 创建用户信息结构体
        UserInfo user;
        strncpy(user.username, username, sizeof(user.username) - 1);
        strncpy(user.password, password, sizeof(user.password) - 1);
        strncpy(user.role, role, sizeof(user.role) - 1);
        
        // 插入用户信息
        if (dbInsertUser(conn, &user) == 0) {
            // 注册成功
            cJSON *response = cJSON_CreateObject();
            char *responseStr = cJSON_PrintUnformatted(response);
            sendPacket(client->sockfd, DATA_TYPE_ACK, responseStr);
            free(responseStr);
            cJSON_Delete(response);
            
            logInfo("User registration successful: %s", username);
            
            // 记录日志到数据库
            time_t now = time(NULL);
            char timeStr[20];
            strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", localtime(&now));
            dbInsertLog(conn, (int)now, timeStr, "", "User registration successful");
        } else {
            // 注册失败
            cJSON *response = cJSON_CreateObject();
            cJSON_AddStringToObject(response, "error", "Failed to register user");
            char *responseStr = cJSON_PrintUnformatted(response);
            sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
            free(responseStr);
            cJSON_Delete(response);
        }
    }
    
    dbDisconnect(conn);
}

// 线程池任务处理函数
void handleClientData(void *arg) {
    TaskData *task = (TaskData *)arg;
    ClientInfo *client = task->client;
    char *data = task->data;
    unsigned char dataType = task->dataType;
    
    logDebug("Processing data type %d from client %s:%d", 
            dataType, inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port));
    
    // 解析JSON数据
    cJSON *root = cJSON_Parse(data);
    if (root) {
        // 根据数据类型处理
        switch (dataType) {
            case DATA_TYPE_SILICON_WAFER:
                processSiliconWaferData(client, root);
                break;
            case DATA_TYPE_PRODUCTION:
                processProductionData(client, root);
                break;
            case DATA_TYPE_HEARTBEAT:
                // 更新连接状态
                connectionStatusUpdate(client->connStatus);
                logDebug("Received heartbeat from client %s:%d", 
                        inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port));
                break;
            case DATA_TYPE_USER_LOGIN:
                handleUserLogin(client, root);
                break;
            case DATA_TYPE_USER_REGISTER:
                handleUserRegister(client, root);
                break;
            default:
                logWarning("Unknown data type: %d from client %s:%d", 
                        dataType, inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port));
                break;
        }
        
        // 发送确认包
        cJSON *response = cJSON_CreateObject();
        cJSON_AddStringToObject(response, "status", "success");
        cJSON_AddNumberToObject(response, "timestamp", time(NULL));
        
        char *responseStr = cJSON_PrintUnformatted(response);
        sendPacket(client->sockfd, DATA_TYPE_ACK, responseStr);
        
        free(responseStr);
        cJSON_Delete(response);
        cJSON_Delete(root);
    } else {
        logError("Failed to parse JSON data from client %s:%d", 
                inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port));
        
        // 发送错误包
        cJSON *response = cJSON_CreateObject();
        cJSON_AddStringToObject(response, "status", "error");
        cJSON_AddStringToObject(response, "message", "Invalid JSON format");
        
        char *responseStr = cJSON_PrintUnformatted(response);
        sendPacket(client->sockfd, DATA_TYPE_ERROR, responseStr);
        
        free(responseStr);
        cJSON_Delete(response);
    }
    
    free(data);
    free(task);
}

// 设置非阻塞模式
int setNonBlocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    if (flags < 0) {
        return -1;
    }
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

// 添加客户端到epoll
void addClientToEpoll(int epollfd, int sockfd, struct sockaddr_in addr) {
    struct epoll_event event;
    
    // 创建客户端信息
    ClientInfo *client = (ClientInfo *)malloc(sizeof(ClientInfo));
    client->sockfd = sockfd;
    client->addr = addr;
    client->connStatus = connectionStatusInit();
    
    // 设置非阻塞
    setNonBlocking(sockfd);
    
    // 添加到epoll
    event.events = EPOLLIN | EPOLLET;
    event.data.ptr = client;
    epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &event);
    
    // 添加到客户端列表
    g_clients[g_clientCount++] = client;
    
    logInfo("New client connected: %s:%d", 
            inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
}

// 从epoll中移除客户端
void removeClientFromEpoll(int epollfd, ClientInfo *client) {
    // 从epoll中移除
    epoll_ctl(epollfd, EPOLL_CTL_DEL, client->sockfd, NULL);
    close(client->sockfd);
    
    // 从客户端列表中移除
    for (int i = 0; i < g_clientCount; i++) {
        if (g_clients[i] == client) {
            g_clients[i] = g_clients[g_clientCount - 1];
            break;
        }
    }
    g_clientCount--;
    
    // 释放资源
    connectionStatusDestroy(client->connStatus);
    free(client);
    
    logInfo("Client disconnected");
}

// 检查客户端连接状态
void checkClientStatus() {
    while (1) {
        sleep(5);  // 每5秒检查一次
        
        for (int i = 0; i < g_clientCount; i++) {
            ClientInfo *client = g_clients[i];
            if (connectionStatusCheckTimeout(client->connStatus, 30)) {  // 30秒超时
                logWarning("Client %s:%d timeout, disconnecting", 
                        inet_ntoa(client->addr.sin_addr), ntohs(client->addr.sin_port));
                removeClientFromEpoll(g_epollfd, client);
                i--;  // 调整索引
            }
        }
    }
}

// 主函数
int main() {
    int serverfd, clientfd;
    struct sockaddr_in /* serverAddr, */ clientAddr;
    socklen_t clientAddrLen;
    struct epoll_event events[MAX_EVENTS];
    pthread_t checkThread;
    
    // 初始化日志
    logInit("server.log", LOG_LEVEL_INFO, 1);
    logInfo("Starting server...");
    
    // 创建线程池
    g_threadPool = threadPoolCreate(THREAD_POOL_SIZE, TASK_QUEUE_SIZE);
    if (!g_threadPool) {
        logFatal("Failed to create thread pool");
    }
    
    // 创建服务器套接字
    serverfd = createTCPServer(SERVER_PORT, 10);
    if (serverfd < 0) {
        logFatal("Failed to create server socket");
    }
    
    // 设置非阻塞
    setNonBlocking(serverfd);
    
    // 创建epoll
    g_epollfd = epoll_create1(0);
    if (g_epollfd < 0) {
        logFatal("Failed to create epoll");
    }
    
    // 添加服务器套接字到epoll
    struct epoll_event event;
    event.events = EPOLLIN | EPOLLET;
    event.data.fd = serverfd;
    epoll_ctl(g_epollfd, EPOLL_CTL_ADD, serverfd, &event);
    
    // 启动连接状态检查线程
    pthread_create(&checkThread, NULL, (void *)checkClientStatus, NULL);
    
    // 设置定时器信号处理
    signal(SIGALRM, hourlySummaryHandler);
    
    // 启动第一个定时器，1小时后执行
    struct itimerval timer;
    timer.it_value.tv_sec = 3600;
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 3600;
    timer.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &timer, NULL);
    
    logInfo("Server started on port %d", SERVER_PORT);
    
    // 主事件循环
    while (1) {
        int numEvents = epoll_wait(g_epollfd, events, MAX_EVENTS, -1);
        if (numEvents < 0) {
            logError("epoll_wait failed: %s", strerror(errno));
            continue;
        }
        
        for (int i = 0; i < numEvents; i++) {
            if (events[i].data.fd == serverfd) {
                // 新客户端连接
                clientAddrLen = sizeof(clientAddr);
                clientfd = accept(serverfd, (struct sockaddr *)&clientAddr, &clientAddrLen);
                if (clientfd < 0) {
                    logError("accept failed: %s", strerror(errno));
                    continue;
                }
                
                if (g_clientCount >= MAX_CLIENT_COUNT) {
                    logWarning("Max client count reached, rejecting connection");
                    close(clientfd);
                    continue;
                }
                
                addClientToEpoll(g_epollfd, clientfd, clientAddr);
            } else {
                // 客户端数据
                ClientInfo *client = (ClientInfo *)events[i].data.ptr;
                
                if (events[i].events & EPOLLIN) {
                    // 接收数据
                    char jsonBuffer[MAX_BUFFER_SIZE];
                    unsigned char dataType;
                    
                    int ret = recvPacket(client->sockfd, jsonBuffer, MAX_BUFFER_SIZE, &dataType);
                    if (ret > 0) {
                        // 创建任务
                        TaskData *task = (TaskData *)malloc(sizeof(TaskData));
                        task->client = client;
                        task->data = strdup(jsonBuffer);
                        task->dataLen = ret;
                        task->dataType = dataType;
                        
                        // 添加到线程池
                        if (threadPoolAddTask(g_threadPool, handleClientData, task) != 0) {
                            logError("Failed to add task to thread pool");
                            free(task->data);
                            free(task);
                        }
                    } else if (ret == 0 || errno != EAGAIN) {
                        // 客户端断开连接或发生错误
                        removeClientFromEpoll(g_epollfd, client);
                    }
                }
            }
        }
    }
    
    // 清理资源
    close(serverfd);
    close(g_epollfd);
    threadPoolDestroy(g_threadPool);
    logCleanup();
    
    return 0;
}

// 定时器信号处理函数，用于每小时统计数据
static void hourlySummaryHandler(int sig) {
    if (sig == SIGALRM) {
        logInfo("Starting hourly production data summary");
        
        MYSQL *conn = dbConnect();
        if (conn) {
            time_t now = time(NULL);
            struct tm *tm = localtime(&now);
            char timeRange[14];
            strftime(timeRange, sizeof(timeRange), "%Y-%m-%d %H:00", tm);
            
            dbSummarizeHourlyData(conn, timeRange);
            dbDisconnect(conn);
        }
        
        // 设置下一个小时的定时器
        struct itimerval timer;
        timer.it_value.tv_sec = 3600;  // 1小时
        timer.it_value.tv_usec = 0;
        timer.it_interval.tv_sec = 3600;  // 重复间隔1小时
        timer.it_interval.tv_usec = 0;
        setitimer(ITIMER_REAL, &timer, NULL);
    }
}